package com.xiaoxiaoyu.framework.inject;

import com.xiaoxiaoyu.framework.core.BeanContainer;
import com.xiaoxiaoyu.framework.inject.annoattion.Autowired;
import com.xiaoxiaoyu.util.ClassUtil;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.Set;

/**
 * @program: simple-Spring
 * @description:
 * @author: 小小鱼
 * @date: 2021-01-28 14:21
 **/
@Slf4j
public class DependentInject {

    private BeanContainer beanContainer;

    public DependentInject(){
        beanContainer=BeanContainer.getInstance();
    }

    public void doIoc(){
        //获取所有的class
        Set<Class<?>> classSet = beanContainer.getClasses();
        if(classSet.isEmpty()){
            log.warn("empty classset in BeanContainer");
            return;
        }
        for (Class<?> targetClass : classSet) {
            //获取所有的成员变量
            Field[] fields = targetClass.getDeclaredFields();
            //判断成员变量是否存在Autowiredx注解
            if(fields.length==0){
                continue;
            }
            for (Field field : fields) {
                if(field.isAnnotationPresent(Autowired.class)){
                    //获取注解的值
                    Autowired annotation = field.getAnnotation(Autowired.class);
                    String autowiredValue = annotation.value();
                    //获取成员的类型
                    Class<?> fieldClass = field.getType();
                    //获取Autowiredx标记的实例
                    Object fieldInstance = getFieldInstance(fieldClass, autowiredValue);
                    if(fieldInstance==null){
                        return;
                    }
                    //注入成员变量中
                    ClassUtil.setField(field,targetClass,fieldClass,true);
                }
            }

        }


    }

    /**
     * 依赖注入底下超类
     * 缺点：尚未解决循环依赖的问题
     * @param fieldClass
     * @param autowiredValue
     * @return
     */
    private Object getFieldInstance(Class<?> fieldClass, String autowiredValue) {
        Object bean = beanContainer.getBean(fieldClass);
        if (bean != null) {
            return bean;
        }else{//去找超子类获取超接口
            Set<Class<?>> classesBySuper = beanContainer.getClassesBySuper(fieldClass);
            if (classesBySuper.size() == 1) {
                return classesBySuper.iterator().next();
            }else{
                if (!autowiredValue.isEmpty()) {
                    for (Class<?> aClass : classesBySuper) {
                        if(autowiredValue.equals(aClass.getSimpleName())){
                            return aClass;
                        }
                    }
                }
            }
            throw new RuntimeException("multiple implemented classes for " + fieldClass.getName() + " please set @Autowired's value to pick one");
        }
    }
}
